/*
********************************************************************************
 * Copyright (C) 2021, xiang.D <dx_65535@163.com>.
 * All right reserved.
 *
 * File Name   : composite.cc
 * Author      :
 * Version     : V1.0
 * Description :
 * Journal     : 2021-11-03 init v1.0
 * Brief       : Blog: https://blog.csdn.net/qq_38750572?spm=1001.2014.3001.5343
 * Others      :
                 Compile command: g++ -Wl,--no-as-needed -std=c++11 composite.cc
********************************************************************************
*/
#include <iostream>
#include <vector>
#include <string>

using namespace std;

class CTree
{
public:

    virtual ~CTree() {}

    virtual CTree* Add(CTree *pNode)
    {
        return pNode;
    }

    virtual int Remove(CTree *pNode)
    {
        cout << "No this function!" << endl;
        return 0;
    }

    virtual string GetName()
    {
        return "";
    }

    virtual bool IsTrunk() const
    {
        return false;
    }

    CTree *mParent;

    CTree *mFirstChild;
    CTree *mLastChild;

    CTree *mPrev;
    CTree *mNext;

    CTree():
        mParent(0),
        mFirstChild(0),
        mLastChild(0),
        mPrev(0),
        mNext(0)
    {}
};

class CTrunk : public CTree
{
public:
    CTree* Add(CTree *pNode)
    {
        if (NULL == pNode) {
            return 0;
        }

        if (mLastChild) {
            pNode->mNext = 0;
            pNode->mPrev = mLastChild;
            mLastChild->mNext = pNode;
            mLastChild = pNode;
        }
        else {

            mFirstChild = mLastChild = pNode;
            pNode->mPrev = 0;
            pNode->mNext = 0;
        }

        pNode->mParent = this;
        return pNode;
    }

    int Remove(CTree *pNode)
    {
        if (NULL == pNode) {
            return -1;
        }
        else {
            cout << "Remove " << pNode->GetName() << endl;
        }

        return 0;
    }

    string GetName() { return mName; }

    bool IsTrunk() const
    {
        return true;
    }

    void ShowBranch()
    {
        CTree *p = mFirstChild;
        while (p)
        {
            cout << p->GetName() << " ";
            p = p->mNext;
        }
        cout << endl;
    }

    void ShowAllBranch(CTree *p)
    {
        CTree *pCurrent = p;

        for (pCurrent = p->mFirstChild; pCurrent; pCurrent = pCurrent->mNext)
        {
            CTree *pTmp = pCurrent;
            cout << pTmp->GetName() << " ";
            if (pTmp->IsTrunk()) {
                ShowAllBranch(pTmp);
            }
            else {
                pTmp = pTmp->mNext;
                cout << endl;
            }
        }
    }

    explicit CTrunk(string Name)
    {
        mName = Name;
    }

    ~CTrunk()
    {}

private:
    string mName;

};

class CLeaf : public CTree
{
public:
    explicit CLeaf(string Name)
    {
        mName = Name;
    }

    ~CLeaf()
    {

    }

    string GetName() { return mName; }

private:
    string mName;
};

//                      root
//                  /    \     \
//                 /      \     \
//               branch1 branch2 leaf
//              /   \         \
//             /     \         \
//        branch1_1  leaf1_1  leaf2_1

int main(int argc, char *argv[])
{
    CTrunk theRoot("root");
    CTrunk theBranch1("branch1");
    CTrunk theBranch2("branch2");
    CTrunk theBranch1_1("branch1_1");
    CLeaf  theLeaf("leaf");
    CLeaf  theLeaf1_1("leaf1_1");
    CLeaf  theLeaf2_1("leaf2_1");

    theBranch1.Add(&theBranch1_1);
    theBranch1.Add(&theLeaf1_1);

    theBranch2.Add(&theLeaf2_1);

    theRoot.Add(&theBranch1);
    theRoot.Add(&theBranch2);
    theRoot.Add(&theLeaf);


    theRoot.ShowAllBranch(&theRoot);
    //theRoot.ShowBranch();
    return 0;
}
